package com.gxan.web.controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Vector;

/**
 * 由于每一次请求都要创建一个Servlet，将来会有特别多的servlet，不利于管理
 *
 * Servlet优化
 *
 * /brand/*     *代表对应的方法名
 * /user/*
 *
 * 关键点1：获取最后路径这一个方法名
 * 关键点2：通过反射以及this当前对象获取对应的字节码文件，通过invoke调用其方法完成方法的分发
 */
public class BaseServlet extends HttpServlet {
    /*
        方法的分发

        源码里是通过请求的方式来进行方法的分发，
        但我们需要通过路径名来完成对应的方法分发，因此需要重写
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取对应的请求路径
        String uri = req.getRequestURI();
        //2./brand/*  截取这个*对应的方法名
        int index = uri.lastIndexOf('/');//从后往前数的一个/对应的下标
        //  selectAll?  /selectAll?
        String methodName = uri.substring(index + 1);//这样通过打印结果得知截取的是/methodName  因此需要下标+1来截取完整方法名

        //3.执行方法
        //3.1获取对应的字节码文件 .class
        //谁调用我(this 所在的方法)，我(this)代表谁
        Class<? extends BaseServlet> cls = this.getClass();  //谁是this?  BrandServlet? HttpServlet? BrandServlet?
        try {
            //通过类对象，以及方法名，定位对应的方法
            Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            //执行该方法,完成方法的分发
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
